package edu.sjtu.context.core;

import java.io.FileNotFoundException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.sjtu.context.persist.PersistManager;
import edu.stanford.smi.protegex.owl.jena.JenaOWLModel;
import edu.stanford.smi.protegex.owl.model.OWLDatatypeProperty;
import edu.stanford.smi.protegex.owl.model.OWLIndividual;
import edu.stanford.smi.protegex.owl.model.OWLModel;
import edu.stanford.smi.protegex.owl.model.OWLNamedClass;

/**
 * This class used to collect context information detected by different kinds of probes.
 * It will complete tow tasks. First, it will update the context information of certain 
 * ontologies based on the detected context. Second, it will invocate {@linkplain Action} 
 * classes register in it based on the type of the transformed context.
 * @author Roger
 *
 */
public class ContextGauge implements 
	LocalContextChangeListener, RemoteContextChangeListener {
	/**
	 * Single instance.
	 */
	private static ContextGauge gauge = null;
	
	/**
	 * log instance
	 */
	private static Log log = null;
	
	/**
	 * static inner class to initialize ContextGauge
	 * @author Roger
	 *
	 */
	static class ContextGaugeHolder{
		static volatile ContextGauge cg = new ContextGauge();
	}
	/**
	 * Private constuctory.
	 * 
	 * @author Roger
	 */
	private ContextGauge(){
		log = LogFactory.getLog(this.getClass());
	}
	
	/**
	 * Return the single instance. If it is first used this method will create a new instance. Or
	 * it return the single instance. 
	 * @return
	 * 		The single instance.
	 * @author Roger
	 */
	public static ContextGauge getInstance(){
		return ContextGaugeHolder.cg;
	}
	
	/**
	 * callback method used by {@link LocalContextProb}.
	 * 
	 * @author Roger
	 */
	public synchronized void sendLocalContext(ContextChangeEvent event){
		log.info("Detect local context change. Context Name:" + event.getContextName() + ", new Context Value:" + event.getContextValue());
		try {
			Object obj = event.getSource();
			if(obj instanceof PublishContext){
				PublishContext pc = (PublishContext)obj;
				ContextMessage msg = new ContextMessage(event.getClassName(), 
						event.getContextName(), event.getContextValue());
				ContextManager.getInstance().getTopicManager().publish(pc.getTopic(), msg);
			}
			
			JenaOWLModel model = ContextManager.getInstance().getLocalOntology();
			OWLNamedClass environment = model.getOWLNamedClass("intont:" + event.getClassName());
			OWLIndividual enInd = model.getOWLIndividual(event.getClassName() + "Individual");
			if(enInd == null){
				enInd = environment.createOWLIndividual(event.getClassName() + "Individual");
			}
			OWLDatatypeProperty property = model.getOWLDatatypeProperty("intont:" + event.getContextName());
			enInd.setPropertyValue(property, event.getContextValue());
			ContextManager.getInstance().updateLocalContextOntology();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * callback method used by {@link RemoteContextProb}.
	 * 
	 * @author Roger
	 */
	public synchronized void sendRemoteContext(ContextChangeEvent event){
		System.out.println(event.getContextName() + ":" + event.getContextValue());
		PersistManager pm = ContextManager.getInstance().getPersistManager();
		JenaOWLModel model = pm.getOntology(event.getOntName());
		
		if(model == null){
			log.debug("Can't update context infomation. Ontology with name:" + event.getOntName() + " not exist.");
			return;
		}
		
		OWLNamedClass cls = model.getOWLNamedClass("intont:" + event.getClassName());
		OWLIndividual individual = model.getOWLIndividual(event.getClassName() + "Individual");
		if(individual == null){
			individual = cls.createOWLIndividual(event.getClassName() + "Individual");
		}
		OWLDatatypeProperty property = model.getOWLDatatypeProperty("intont:" + event.getContextName());
		individual.setPropertyValue(property, event.getContextValue());
		
		pm.updateOntology(model, event.getOntName());
	}
}
